package util

import (
	"github.com/kordar/goutil"
	"github.com/kordar/k-means-server/src/pojo"
	"github.com/spf13/cast"
	"log"
	"math"
	"strings"
)

type Result struct {
	Code  int `json:"code"`
	Count int `json:"count"`
	Data  []struct {
		Img     string `json:"img"`
		Feature string `json:"feature"`
	} `json:"data"`
}

func GetFeature(data string, featureUrl string) []float64 {
	var result Result
	var float64s []float64
	if _, err := goutil.PostBodyHeader(featureUrl, []string{data}, nil, &result); err == nil {
		if len(result.Data) > 0 {
			left := strings.TrimLeft(result.Data[0].Feature, "[")
			right := strings.TrimRight(left, "]")
			split := strings.Split(right, ",")
			float64s = make([]float64, len(split))
			// log.Println("len=", len(split))
			for i, s := range split {
				val := strings.TrimSpace(s)
				float64s[i] = cast.ToFloat64(val)
			}
			// log.Println("len2=", len(float64s))
		}
	} else {
		log.Println(err)
	}
	return float64s
}

func Cosine(a []float64, b []float64) float64 {
	var (
		aLen  = len(a)
		bLen  = len(b)
		s     = 0.0
		sa    = 0.0
		sb    = 0.0
		count = 0
	)
	if aLen > bLen {
		count = aLen
	} else {
		count = bLen
	}
	for i := 0; i < count; i++ {
		if i >= bLen {
			sa += math.Pow(a[i], 2)
			continue
		}
		if i >= aLen {
			sb += math.Pow(b[i], 2)
			continue
		}
		s += a[i] * b[i]
		sa += math.Pow(a[i], 2)
		sb += math.Pow(b[i], 2)
	}
	return s / (math.Sqrt(sa) * math.Sqrt(sb))
}

func StringToFloat64Array(str string) []float64 {
	left := strings.TrimLeft(str, "[")
	right := strings.TrimRight(left, "]")
	split := strings.Split(right, ",")
	float64s := make([]float64, len(split))
	// log.Println("len=", len(split))
	for i, s := range split {
		val := strings.TrimSpace(s)
		float64s[i] = cast.ToFloat64(val)
	}
	return float64s
}

// GetMaxCompare source 与 targetData 比较，将最小距离返回
func GetMaxCompare(source []pojo.FeatureItem, target pojo.FeatureItem, m map[string][]float64) pojo.FeatureItem {
	var max float64 = 0
	var cosine float64 = 0
	var targetData pojo.FeatureItem
	for _, data := range source {
		if data.Id == target.Id {
			return data
		} else {
			cosine = Cosine(m[data.Url], m[target.Url])
		}
		if cosine > max {
			max = cosine
			targetData = data
		}
	}
	return targetData
}

func GetCenterByCompareSum(group []pojo.FeatureItem, m map[string][]float64) pojo.FeatureItem {
	res := make(map[int]float64, len(group))
	max := 0.0
	var maxItem pojo.FeatureItem = group[0]
	for _, item := range group {
		id := item.Id
		res[id] = 0
		for _, featureItem := range group {
			id2 := featureItem.Id
			if id != id2 {
				cosine := Cosine(m[item.Url], m[featureItem.Url])
				res[id] += cosine
			}
		}

		if res[id] > max {
			max = res[id]
			maxItem = item
		}

	}

	return maxItem
}

/*func GetMaxCompare(source []entity.FeatureData, targetData []float64, targetId string) entity.CosineData {
	var max float64 = 0
	var cosine float64 = 0
	cosineData := entity.CosineData{}
	for _, data := range source {
		if data.Id == targetId {
			cosine = 1
		} else {
			cosine = Cosine(data.Data, targetData)
		}
		if cosine > max {
			max = cosine
			cosineData.Score = cast.ToString(max)
			cosineData.SourceId = data.Id
			cosineData.TargetId = targetId
		}
	}
	return cosineData
}*/

/*func ArrayInGroupsOf(arr []entity.SimilarityItem, num int64) [][]entity.SimilarityItem {
	max := int64(len(arr))
	//判断数组大小是否小于等于指定分割大小的值，是则把原数组放入二维数组返回
	if max <= num {
		return [][]entity.SimilarityItem{arr}
	}
	//获取应该数组分割为多少份
	var quantity int64
	if max%num == 0 {
		quantity = max / num
	} else {
		quantity = (max / num) + 1
	}
	//声明分割好的二维数组
	var segments = make([][]entity.SimilarityItem, 0)
	//声明分割数组的截止下标
	var start, end, i int64
	for i = 1; i <= quantity; i++ {
		end = i * num
		if i != quantity {
			segments = append(segments, arr[start:end])
		} else {
			segments = append(segments, arr[start:])
		}
		start = i * num
	}
	return segments
}
*/
